home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / editors / emacs / xemacs / xemacs-1.004 / xemacs-1 / xemacs-19.13 / src / sunplay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-20  |  7.2 KB  |  335 lines

  1. /* play.c - play a sound file on the speaker
  2.  **
  3.  ** Copyright (C) 1989 by Jef Poskanzer.
  4.  **
  5.  ** Modified 24-May-91 by Jamie Zawinski (for Lucid Emacs).
  6.  ** Modified 17-Dec-92 by Jamie Zawinski (largely rewritten for SunOS 4.1.3).
  7.  **
  8.  ** Permission to use, copy, modify, and distribute this software and its
  9.  ** documentation for any purpose and without fee is hereby granted, provided
  10.  ** that the above copyright notice appear in all copies and that both that
  11.  ** copyright notice and this permission notice appear in supporting
  12.  ** documentation.  This software is provided "as is" without express or
  13.  ** implied warranty.
  14.  */
  15.  
  16. /* Synched up with: Not in FSF. */
  17.  
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21.  
  22. #if __STDC__ || defined(STDC_HEADERS)
  23. #include <stdlib.h>
  24. #include <unistd.h>
  25. #include <fcntl.h>    /* for open() */
  26. #endif
  27.  
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <sys/signal.h>
  31. #include <sys/fcntl.h>
  32. #include <sys/file.h>
  33.  
  34. #include <multimedia/libaudio.h>
  35. #include <multimedia/audio_device.h>
  36.  
  37. #if __STDC__ || defined(STDC_HEADERS)           /* warning suppression */
  38. extern int audio__setplayhdr();
  39. extern int audio__setgain();
  40. extern int audio__flush();
  41. extern int audio_decode_filehdr();
  42. extern int audio_read_filehdr();
  43. extern int audio_cmp_hdr();
  44. extern int audio_enc_to_str();
  45. extern int audio_drain();
  46. extern void usleep();
  47. #endif
  48.  
  49.  
  50. #ifdef emacs
  51. # include <config.h>
  52. # include "lisp.h"
  53. # include "sysdep.h"
  54. # include "emacsfns.h"
  55. # include <errno.h>
  56. # define perror(string) \
  57.     message("audio: %s, %s ", string, strerror (errno))
  58. # define warn(str) message ("audio: %s ", GETTEXT (str))
  59. #else /* !emacs */
  60. # define warn(str) fprintf (stderr, "%s\n", (str))
  61. #endif /* emacs */
  62.  
  63. static SIGTYPE (*sighup_handler) ();
  64. static SIGTYPE (*sigint_handler) ();
  65. static SIGTYPE sighandler (int sig);
  66.  
  67. static int audio_fd;
  68.  
  69. #define audio_open()    open ("/dev/audio", (O_WRONLY | O_NDELAY), 0)
  70.  
  71. static int reset_volume_p, reset_device_p;
  72. static double old_volume;
  73. static Audio_hdr dev_hdr;
  74.  
  75. void play_sound_file (char *name, int volume);
  76. void play_sound_data (unsigned char *data, int length, int volume);
  77.  
  78. static int
  79. init_device (int volume, unsigned char *data, int fd,
  80.          unsigned int *header_length)
  81. {
  82. #ifdef SUNOS4_0_3
  83.   if (header_length) *header_length = 0;
  84.   return 0;
  85. #else
  86.   Audio_hdr file_hdr;
  87.   
  88.   reset_volume_p = 0;
  89.   reset_device_p = 0;
  90.  
  91.   if (data && fd) abort (); /* one or the other */
  92.  
  93.   if (AUDIO_SUCCESS != audio_get_play_config (audio_fd, &dev_hdr))
  94.     {
  95.       perror ("Not a valid audio device");
  96.       return 1;
  97.     }
  98.   
  99.   if (AUDIO_SUCCESS != (data
  100.             ? audio_decode_filehdr (data, &file_hdr, header_length)
  101.             : audio_read_filehdr (fd, &file_hdr, 0, 0)))
  102.     {
  103.       if (data)
  104.     perror ("invalid audio data");
  105.       else
  106.     perror ("invalid audio file");
  107.       return 1;
  108.     }
  109.   
  110.   audio_flush_play (audio_fd);
  111.  
  112.   if (0 != audio_cmp_hdr (&dev_hdr, &file_hdr))
  113.     {
  114.       Audio_hdr new_hdr;
  115.       new_hdr = file_hdr;
  116.       reset_device_p = 1;
  117.       if (AUDIO_SUCCESS != audio_set_play_config (audio_fd, &new_hdr))
  118.     {
  119.       char buf1 [100], buf2 [100], buf3 [250];
  120.       audio_enc_to_str (&file_hdr, buf1);
  121.       audio_enc_to_str (&new_hdr, buf2);
  122.       sprintf (buf3, "wanted %s, got %s", buf1, buf2);
  123.       warn (buf3);
  124.       return 1;
  125.     }
  126.     }
  127.  
  128.   if (volume < 0 || volume > 100)
  129.     {
  130.       char buf [255];
  131.       sprintf (buf, "volume must be between 0 and 100 (not %d)", volume);
  132.       warn (buf);
  133.       return 1;
  134.     }
  135.   {
  136.     /* set the volume; scale it to 0.0 - 1.0 */
  137.     double V = (volume / 100.0);
  138.     audio_get_play_gain (audio_fd, &old_volume);
  139.     reset_volume_p = 1;
  140.     audio_set_play_gain (audio_fd, &V);
  141.   }
  142.  
  143.   return 0;
  144. #endif
  145. }
  146.  
  147.  
  148. static void
  149. reset_device (int wait_p)
  150. {
  151.   if (wait_p)
  152.     audio_drain (audio_fd, 1);
  153.   else
  154.     audio_flush_play (audio_fd);
  155.   if (reset_device_p)
  156.     audio_set_play_config (audio_fd, &dev_hdr);
  157.   if (reset_volume_p)
  158.     audio_set_play_gain (audio_fd, &old_volume);
  159. }
  160.  
  161.  
  162. void
  163. play_sound_file (char *sound_file, int volume)
  164. {
  165.   int rrtn, wrtn;
  166.   unsigned char buf [255];
  167.   int file_fd;
  168.   
  169.   audio_fd = audio_open ();
  170.  
  171.   if (audio_fd < 0)
  172.     {
  173.       perror ("open /dev/audio");
  174.       return;
  175.     }
  176.  
  177.   /* where to find the proto for signal()... */
  178.   sighup_handler = (SIGTYPE (*) (int)) signal (SIGHUP, sighandler);
  179.   sigint_handler = (SIGTYPE (*) (int)) signal (SIGINT, sighandler);
  180.   
  181.   file_fd = open (sound_file, O_RDONLY, 0);
  182.   if (file_fd < 0)
  183.     {
  184.       perror (sound_file);
  185.       goto END_OF_PLAY;
  186.     }
  187.  
  188.   if (init_device (volume, (unsigned char *) 0, file_fd, (unsigned int *) 0))
  189.     goto END_OF_PLAY;
  190.     
  191.   while (1)
  192.     {
  193.       rrtn = read (file_fd, (char *) buf, sizeof (buf));
  194.       if (rrtn < 0)
  195.     {
  196.       perror ("read");
  197.       goto END_OF_PLAY;
  198.     }
  199.       if (rrtn == 0)
  200.     break;
  201.     
  202.       while (1)
  203.     {
  204.       wrtn = write (audio_fd, (char *) buf, rrtn);
  205.       if (wrtn < 0)
  206.         {
  207.           perror ("write");
  208.           goto END_OF_PLAY;
  209.         }
  210.       if (wrtn != 0)
  211.         break;
  212.  
  213.       if (AUDIO_ERR_INTERRUPTED == audio_drain (audio_fd, 1))
  214.         goto END_OF_PLAY;
  215.     }
  216.       if (wrtn != rrtn)
  217.     {
  218.       char buf [255];
  219.       sprintf (buf, "play: rrtn = %d, wrtn = %d", rrtn, wrtn);
  220.       warn (buf);
  221.       goto END_OF_PLAY;
  222.     }
  223.     }
  224.   
  225.  END_OF_PLAY:
  226.  
  227.   if (file_fd > 0)
  228.     close (file_fd);
  229.  
  230.   if (audio_fd > 0)
  231.     {
  232.       reset_device (1);
  233.       close (audio_fd);
  234.     }
  235.  
  236.   (void) signal (SIGHUP, sighup_handler);
  237.   (void) signal (SIGINT, sigint_handler);
  238. }
  239.  
  240.  
  241. void
  242. play_sound_data (unsigned char *data, int length, int volume)
  243. {
  244.   int wrtn, start = 0;
  245.   unsigned int ilen;
  246.  
  247.   audio_fd = -1;
  248.  
  249.   if (length == 0) return;
  250.  
  251.   /* this is just to get a better error message */
  252.   if (strncmp (".snd\0", (char *) data, 4))
  253.     {
  254.       warn ("Not valid audio data (bad magic number)");
  255.       goto END_OF_PLAY;
  256.     }
  257.   if (length <= sizeof (Audio_hdr))
  258.     {
  259.       warn ("Not valid audio data (too short)");
  260.       goto END_OF_PLAY;
  261.     }
  262.  
  263.   audio_fd = audio_open ();
  264.   if (audio_fd < 0)
  265.     {
  266.       perror ("open /dev/audio");
  267.       return;
  268.     }
  269.  
  270.   /* where to find the proto for signal()... */
  271.   sighup_handler = (SIGTYPE (*) (int)) signal (SIGHUP, sighandler);
  272.   sigint_handler = (SIGTYPE (*) (int)) signal (SIGINT, sighandler);
  273.     
  274.   if (init_device (volume, data, 0, &ilen))
  275.     goto END_OF_PLAY;
  276.       
  277.   data   += (ilen<<2);
  278.   length -= (ilen<<2);
  279.   if (length <= 1)
  280.     goto END_OF_PLAY;
  281.     
  282.   while (1)
  283.     {
  284.       wrtn = write (audio_fd, (char *) (data+start), length-start);
  285.       if (wrtn < 0)
  286.     {
  287.       perror ("write");
  288.       goto END_OF_PLAY;
  289.     }
  290.       if (wrtn != 0)
  291.     {
  292.       start += wrtn;
  293.       break;
  294.     }
  295.       if (AUDIO_ERR_INTERRUPTED == audio_drain (audio_fd, 1))
  296.     goto END_OF_PLAY;
  297.     }
  298.   if (wrtn != length)
  299.     {
  300.       char buf [255];
  301.       sprintf (buf, "play: rrtn = %d, wrtn = %d", length, wrtn);
  302.       warn (buf);
  303.       goto END_OF_PLAY;
  304.     }
  305.   
  306.  END_OF_PLAY:
  307.  
  308.   if (audio_fd > 0)
  309.     {
  310.       reset_device (1);
  311.       close (audio_fd);
  312.     }
  313.  
  314.   (void) signal (SIGHUP, sighup_handler);
  315.   (void) signal (SIGINT, sigint_handler);
  316. }
  317.  
  318. /* #### sigcontext doesn't exist in Solaris.  This should be updated
  319.    to be correct for Solaris. */
  320. static void
  321. sighandler (int sig)
  322. {
  323.   if (audio_fd > 0)
  324.     {
  325.       reset_device (0);
  326.       close (audio_fd);
  327.     }
  328.   if (sig == SIGHUP && sighup_handler)
  329.     sighup_handler (sig);
  330.   else if (sig == SIGINT && sigint_handler)
  331.     sigint_handler (sig);
  332.   else
  333.     exit (1);
  334. }
  335.